﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace AirWar
{
    public partial class FormMain : Form
    {
        Bitmap imgGameOver;
        #region 私有字段
        //游戏状态
        private GameState _gameState = GameState.Close;
        //地图类对象
        private Map _map;
        //我方飞机
        private Fighter _myFighter;
        //敌方飞机集合
        private List<Fighter> _listEnemyFighter = new List<Fighter> { };
        
        //我方子弹集合
        private List<Bullet> _listMyBullet = new List<Bullet> { };
        
        //敌方子弹集合
        private List<Bullet> _listEnemyBullet = new List<Bullet> { };
        
        //项目exe文件所在路径
        private string _exePath = "";
        //ini配置文件的路径和名称
        private string _iniPathFile = "";
        //玩家目前最高分
        private int _maxScore = 0;

        #endregion
        //导入动态链接库的键盘检测api函数
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
        //异步检测键盘按键是否按下
        public static extern short GetAsyncKeyState(int keyCode);

        //导入动态链接库（kernel32.dll）的ini配置文件读写函数
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
        
        public FormMain()
        {
            InitializeComponent();
            _map = new Map("Image\\mapDesert.jpg");
            //生成一架我方飞机
            _myFighter = new Fighter(Side.Me, _map._Size);
            
            //设置项目exe文件的完整路径和文件名
            string exePathFileName = Process.GetCurrentProcess().MainModule.FileName;
            //设置项目完整路径（去除文件名）
            _exePath = System.IO.Path.GetDirectoryName(exePathFileName) + "\\";
            //设置ini配置文件的路径和名称
            _iniPathFile = _exePath + "Setting.ini";
            //从ini文件读取最高分
            try
            {
                _maxScore = Convert.ToInt32(ReadStringFromIni("score", "maxScore"));
            }
            catch
            { 
                //如果无法从配置文件读取最大得分。取默认值0；
                _maxScore = 0;
            }
        }
        //窗口加载事件
        private void FormMain_Load(object sender, EventArgs e)
        {
            //设置主窗口尺寸等于地图图片的尺寸
            this.ClientSize = _map._Size;
            //让窗口顶部对齐屏幕顶部
            this.Top = 0;
            //设置media不可见
            axWindowsMediaPlayerBgMusic.Visible = false;
            //自动播放
            axWindowsMediaPlayerBgMusic.URL = "Sound\\backgroundMusic.mp3";
            axWindowsMediaPlayerBgMusic.Ctlcontrols.play();

            //同上
            axWindowsMediaPlayerExplode.Visible = false;
            axWindowsMediaPlayerExplode.URL = "Sound\\fighterExplode.wav";
            axWindowsMediaPlayerExplode.Ctlcontrols.stop();

            axWindowsMediaPlayerHitFighter.Visible = false;
            axWindowsMediaPlayerHitFighter.URL = "Sound\\hitMyFighter.wav";
            axWindowsMediaPlayerHitFighter.Ctlcontrols.stop();
        }
        //pictureBoxMap组件的Paint事件响应方法
        private void pictureBoxMap_Paint(object sender, PaintEventArgs e)
        {
            //绘制地图
            _map.DrawMe(e.Graphics);
            //处理我方子弹击中敌方飞机
            MyBulletHitEnemyFighter();
            //处理敌方子弹击中我方飞机
            EnemyBulletHitMyFighter();
            //处理敌方飞机撞击我方飞机
            EnemyFighterHitMyFighter();
            

            //移除失效的我方子弹
            for (int i = _listMyBullet.Count - 1; i >= 0; i--)
            {
                if (_listMyBullet[i]._Enable == false || _listMyBullet[i]._Position.Y <= -10)
                    _listMyBullet.RemoveAt(i);
            }
            //移除生命值为0的敌方飞机,或越界的飞机
            for(int i = _listEnemyFighter.Count - 1; i >= 0; i--)
                if(_listEnemyFighter[i]._LifeValue == 0 || _listEnemyFighter[i]._Postion.Y >= _map._Size.Height)
                {
                    //如果敌方飞机的生命值为0，表明该飞机被击毁，绘制出敌方飞机爆炸效果
                    if (_listEnemyFighter[i]._LifeValue == 0)
                    {
                        _listEnemyFighter[i].Explode(e.Graphics);
                    }
                    //移除该飞机
                    _listEnemyFighter.RemoveAt(i);
                }
            //移除失效的敌方子弹
            for (int i = _listEnemyBullet.Count - 1; i >= 0; i--)
                if (_listEnemyBullet[i]._Enable == false || _listEnemyBullet[i]._Position.Y >= _map._Size.Height)
                    _listEnemyBullet.RemoveAt(i);
            //我们生命值大于0，则绘制出我方飞机
            if (_myFighter._LifeValue > 0)
                _myFighter.DrawMe(e.Graphics);
            //逐一绘制敌方飞机
            foreach (Fighter enemyFighter in _listEnemyFighter)
                enemyFighter.DrawMe(e.Graphics);
            //逐一绘制我方子弹
            foreach (Bullet myBullet in _listMyBullet)
                myBullet.DrawMe(e.Graphics);
            //逐一绘制敌方子弹
            foreach (Bullet enemyBullet in _listEnemyBullet)
                enemyBullet.DrawMe(e.Graphics);
            //绘制我方飞机的生命值和分数
            e.Graphics.DrawRectangle(new Pen(Color.Black), new Rectangle(10, 40, 101, 10));
            e.Graphics.FillRectangle(Brushes.Red, 11, 41, _myFighter._LifeValue, 9);
            e.Graphics.DrawString("得分：" + _myFighter._Score, new Font("宋体",9,FontStyle.Bold),
                                   Brushes.Yellow, new Point(10, 60));
            e.Graphics.DrawString("榜首：" + _maxScore, new Font("宋体", 9, FontStyle.Bold),
                                   Brushes.Yellow, new Point(10, 100));
            //如果我方生命值≤0，游戏结束
            if (_myFighter._LifeValue <= 0)
            {
                imgGameOver = new Bitmap("Image\\gameOver.png");
                //在地图中间位置加载提示画面
                e.Graphics.DrawImage(imgGameOver, (_map._Size.Width - imgGameOver.Width) / 2, (_map._Size.Height - imgGameOver.Height) / 2);
                //结束游戏
                _gameState = GameState.Close;

                //如果得分大于最高峰，则更新最高分，并提示
                if (_myFighter._Score >= _maxScore)
                {
                    _maxScore = _myFighter._Score;
                    e.Graphics.DrawString("您的得分为" + _myFighter._Score.ToString() + ",恭喜你荣登得分榜榜首!",
                                           new Font("微软雅黑", 16, FontStyle.Bold), Brushes.Yellow,
                                           new Point(28, _map._Size.Height / 2 + 60));
                }
            }
        }
        //定时器的tick事件，让地图滚动并强制刷新PictureBox组件
        private void timerPaintPictureBox_Tick(object sender, EventArgs e)
        {
            //地图向下滚动两个像素点
            _map.Scroll(2);
            //实现我方飞机的方向控制和子弹发射
            if (_gameState == GameState.Open)
            { 
                //检测我方飞机的方向按键
                bool downPressed = (((ushort)GetAsyncKeyState((int)Keys.Down)) & 0xffff) != 0;
                if (downPressed == true)
                    _myFighter.Move(Direction.Down, _map._Size);
                bool upPressed = (((ushort)GetAsyncKeyState((int)Keys.Up)) & 0xffff) != 0;
                if (upPressed == true)
                    _myFighter.Move(Direction.Up, _map._Size);
                bool leftPressed = (((ushort)GetAsyncKeyState((int)Keys.Left)) & 0xffff) != 0;
                if (leftPressed == true)
                    _myFighter.Move(Direction.Left, _map._Size);
                bool rightPressed = (((ushort)GetAsyncKeyState((int)Keys.Right)) & 0xffff) != 0;
                if (rightPressed == true)
                    _myFighter.Move(Direction.Right, _map._Size);
                //检测我方飞机的开火按键
                bool spacePressed = (((ushort)GetAsyncKeyState((int)Keys.Space)) & 0xffff) != 0;
                if (spacePressed == true)
                { 
                    //产生一个子弹添加到我方list
                    Bullet myBullet = _myFighter.Fire();
                    _listMyBullet.Add(myBullet);
                }
            }
            //按一定概率控制敌方飞机的移动方向
            Random enemyRand = new Random(DateTime.Now.Second);
            foreach (Fighter enemyFighter in _listEnemyFighter)
            { 
                //产生一个随机数
                int direction = enemyRand.Next(1, 6);
                //让敌方飞机移动一个步长
                if (direction == 1)
                    enemyFighter.Move(Direction.Left, _map._Size);
                else if (direction == 2)
                    enemyFighter.Move(Direction.Right, _map._Size);
                else
                    enemyFighter.Move(Direction.Down, _map._Size);
            }
            //让我方子弹飞起来
            foreach (Bullet myBullet in _listMyBullet)
                myBullet.Move();
            //让敌方子弹飞起来
            foreach(Bullet enemyBullet in _listEnemyBullet)
                enemyBullet.Move();
            //强制刷新pictureBoxMap控件
            pictureBoxMap.Invalidate();
        }
        //荒漠响应
        private void ToolStripMenuItemMapDesert_Click(object sender, EventArgs e)
        {
            //新建地图对象
            _map = new Map("Image\\mapDesert.jpg");
            //打勾
            ToolStripMenuItemMapDesert.Checked = true;
            ToolStripMenuItemMapForest.Checked = false;
            ToolStripMenuItemMapCastle.Checked = false;
            ToolStripMenuItemMapBase.Checked = false;
            //强制刷新
            pictureBoxMap.Invalidate();
        }
        //森林响应
        private void ToolStripMenuItemMapForest_Click(object sender, EventArgs e)
        {
            _map = new Map("Image\\mapForest.jpg");
            ToolStripMenuItemMapDesert.Checked = false;
            ToolStripMenuItemMapForest.Checked = true;
            ToolStripMenuItemMapCastle.Checked = false;
            ToolStripMenuItemMapBase.Checked = false;
            pictureBoxMap.Invalidate();
        }
        //城堡响应
        private void ToolStripMenuItemMapCastle_Click(object sender, EventArgs e)
        {
            _map = new Map("Image\\mapCastle.jpg");
            ToolStripMenuItemMapDesert.Checked = false;
            ToolStripMenuItemMapForest.Checked = false;
            ToolStripMenuItemMapCastle.Checked = true;
            ToolStripMenuItemMapBase.Checked = false;
            pictureBoxMap.Invalidate();
        }
        //基地响应
        private void ToolStripMenuItemMapBase_Click(object sender, EventArgs e)
        {
            _map = new Map("Image\\mapBase.jpg");
            ToolStripMenuItemMapDesert.Checked = false;
            ToolStripMenuItemMapForest.Checked = false;
            ToolStripMenuItemMapCastle.Checked = false;
            ToolStripMenuItemMapBase.Checked = true;
            pictureBoxMap.Invalidate();
        }
        //游戏开始
        private void ToolStripMenuItemGameBegin_Click(object sender, EventArgs e)
        {
            //设置游戏状态为Open
            _gameState = GameState.Open;

            //重新生成一架我方飞机
            _myFighter = new Fighter(Side.Me, _map._Size);

            //清空敌方飞机列表
            _listEnemyFighter.Clear();
            //清空子弹
            _listMyBullet.Clear();
            _listEnemyBullet.Clear();

            //重新播放音乐
            axWindowsMediaPlayerBgMusic.Ctlcontrols.stop();
            axWindowsMediaPlayerBgMusic.Ctlcontrols.play();
        }
        //游戏结束
        private void ToolStripMenuItemGameEnd_Click(object sender, EventArgs e)
        {
            //我方飞机生命值设置为0
            _myFighter._LifeValue = 0;
            //设置游戏状态为Close
            _gameState = GameState.Close;
        }
        //键盘下压事件
        private void FormMain_KeyDown(object sender, KeyEventArgs e)
        {
            
        }

        private void timerGenerateEnemyFighter_Tick(object sender, EventArgs e)
        {
            //如果处于open状态
            if (_gameState == GameState.Open)
            { 
                //定时产生一架敌方飞机
                Fighter enemyFighter = new Fighter(Side.Enemy, _map._Size);
                //把敌方飞机加入到list集合中
                _listEnemyFighter.Add(enemyFighter);
                
            }
        }

        private void timerEnemyFighterFire_Tick(object sender, EventArgs e)
        {
            //定义一个随机数，生成敌方飞机开火的概率
            Random myRand = new Random(DateTime.Now.Second);
            //让敌方飞机义一定概率开火
            foreach (Fighter enemyFighter in _listEnemyFighter)
            { 
                //产生一个随机数决定是否开火
                int fireFlag = myRand.Next(1, 7);
                if (fireFlag <= 4)
                { 
                    // 发射子弹
                    Bullet enemyBullet = enemyFighter.Fire();
                    //子弹加入到集合中
                    _listEnemyBullet.Add(enemyBullet);
                }
            }
        }

        //我方子弹击中敌方飞机
        public void MyBulletHitEnemyFighter()
        { 
            //遍历我方子弹
            for (int i = 0; i <= _listMyBullet.Count - 1; i++)
            { 
                //遍历敌方飞机
                for (int j = 0; j <= _listEnemyFighter.Count - 1; j++)
                { 
                    //我方子弹所处的Rectangle对象
                    Rectangle myBulletRect = new Rectangle(_listMyBullet[i]._Position.X, _listMyBullet[i]._Position.Y,
                                                           _listMyBullet[i]._Size.Width, _listMyBullet[i]._Size.Height);
                    //敌方飞机所处的Rectangle
                    Rectangle enemyFighterRect = new Rectangle(_listEnemyFighter[j]._Postion.X, _listEnemyFighter[j]._Postion.Y,
                                                               _listEnemyFighter[j]._Size.Width, _listEnemyFighter[j]._Size.Height);
                    //如果我方子弹的Rectangle对象与敌方飞机的Rectangle对象有交叉，则表明我方子弹击中敌方飞机
                    if (myBulletRect.IntersectsWith(enemyFighterRect))
                    { 
                        //我方飞机的积分+1
                        _myFighter._Score += 1;
                        //敌方飞机的生命值变为0
                        _listEnemyFighter[j]._LifeValue = 0;
                        //我方子弹失效
                        _listMyBullet[i]._Enable = false;

                        //播放音效
                        _listEnemyFighter[j].PlaySound("Sound\\fighterExplode.wav");
                        //一个子弹只能击中一架飞机，所以退出本次循环
                        break;
                    }
                }
            }
        }

        //敌方子弹击中我方飞机
        public void EnemyBulletHitMyFighter()
        {
            //我方飞机还有生命值
            if (_myFighter._LifeValue > 0)
            { 
                //遍历敌方子弹
                for (int i = 0; i <= _listEnemyBullet.Count - 1; i++)
                { 
                    //敌方子弹所处的Rectangle对象
                    Rectangle enemyBulletRect = new Rectangle(_listEnemyBullet[i]._Position.X, _listEnemyBullet[i]._Position.Y,
                                                           _listEnemyBullet[i]._Size.Width, _listEnemyBullet[i]._Size.Height);
                    //我方飞机所处的Rectangle对象
                    Rectangle myFighterRect = new Rectangle(_myFighter._Postion.X, _myFighter._Postion.Y,
                                                              _myFighter._Size.Width, _myFighter._Size.Height);
                
                    //如果两个矩形对象有交叉则表示击中
                    if (enemyBulletRect.IntersectsWith(myFighterRect))
                    { 
                        //我方飞机的生命值-10
                        _myFighter._LifeValue -= 10;
                        //敌方子弹失效
                        _listEnemyBullet[i]._Enable = false;
                        //我方被击中
                        axWindowsMediaPlayerHitFighter.Ctlcontrols.play();
                        
                    }
                }   
            }
        }

        //处理敌方飞机撞击我方飞机
        public void EnemyFighterHitMyFighter()
        { 
            //如果我方飞机还有生命值
            if (_myFighter._LifeValue > 0)
            { 
                //我方飞机所处的Rectangle对象
                Rectangle myFighterRect = new Rectangle(_myFighter._Postion.X, _myFighter._Postion.Y,
                                                              _myFighter._Size.Width, _myFighter._Size.Height);
                //遍历敌方飞机
                for (int i = 0; i <= _listEnemyFighter.Count - 1; i++)
                { 
                    //敌方飞机所处的Rectangle对象
                    Rectangle enemyFighterRect = new Rectangle(_listEnemyFighter[i]._Postion.X, _listEnemyFighter[i]._Postion.Y,
                                                               _listEnemyFighter[i]._Size.Width, _listEnemyFighter[i]._Size.Height);
                    //如果有交叉
                    if (myFighterRect.IntersectsWith(enemyFighterRect))
                    { 
                        //我方飞机生命值-15；
                        _myFighter._LifeValue -= 15;
                        //我方飞机的分加1
                        _myFighter._Score += 1;
                        //敌方飞机生命值变为0
                        _listEnemyFighter[i]._LifeValue = 0;
                        //播放敌方飞机爆炸
                        axWindowsMediaPlayerExplode.Ctlcontrols.play();
                        //播放我方飞机被撞击的音效
                        axWindowsMediaPlayerHitFighter.Ctlcontrols.play();
                    }
                }
            }
        }
        //从_iniPathFile配置文件读取配置信息
        public string ReadStringFromIni(string Section, string Key)
        { 
            //读取配置文件
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(Section, Key, "", temp, 255, _iniPathFile);
            return temp.ToString();
        }
        //向_iniPathFile配置文件写入配置信息
        public void WriteStringToIni(string Section, string Key, string Value)
        { 
            //写入配置信息，如果文件不存在，则自动创建文件
            WritePrivateProfileString(Section, Key, Value, _iniPathFile);
        }
        //窗口关闭时写入最高分在ini配置文件中
        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            //写入最高分
            WriteStringToIni("score", "maxScore", _maxScore.ToString());

        }
    }
}
